package domain.grammar;

import static org.junit.Assert.*;

import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.lang.StackOverflowError;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import domain.parsers.InputGrammarLL1Parser;
import domain.regularExpression.NonUnaryRegularExpressionOperator;
import domain.regularExpression.RegularExpression;
import domain.regularExpression.RegularExpressionElement;
import domain.regularExpression.UnaryRegularExpressionOperator;

//Referencia conflicto01
//S:Aa|a;
//A:Sb|b;

public class ExtendedGrammarTest2 {
	ExtendedGrammar _grammar;
	
	ExtendedProductionSet _productionSet;
	
	ExtendedProduction _production1;
	ExtendedProduction _production2;
	
	ExtendedNonTerminalSymbol _S,_A;
	Set<ExtendedNonTerminalSymbol> _nonTerminals;
	ExtendedTerminalSymbol _a,_b;
	Set<ExtendedTerminalSymbol> _terminals; 
	
	NonUnaryRegularExpressionOperator _pipe, _concat;

	
	RegularExpression _regex1, _regex2;
	
	
	public static String _testnull1 = "S";
	public static String _testnull2 = "A";

	public static String _testfirst1 = "S";
	public static String _testfirst2 = "A";
	
	public static String _testnext1 = "S";
	public static String _testnext2 = "a";
	public static String _testnext3 = "b";
	
	
	
	private ExtendedNonTerminalSymbol findNonTerminal(String name) {
		Iterator<ExtendedNonTerminalSymbol> itnonterminal = _grammar.get_nonTerminals().iterator();
		ExtendedNonTerminalSymbol nonterminal = null;
		while (itnonterminal.hasNext()) {
			nonterminal = itnonterminal.next();
			if (name.equals(nonterminal.getName()) ) break;
		}
		return nonterminal;
	}
	private ExtendedTerminalSymbol findTerminal(String name) {
		Iterator<ExtendedTerminalSymbol> itterminal = _grammar.get_terminals().iterator();
		ExtendedTerminalSymbol terminal = null;
		while (itterminal.hasNext()) {
			terminal = itterminal.next();
			if (name.equals(terminal.getName()) ) break;
		}
		return terminal;
	}
	
	@Before
	public void setUp() throws Exception {
		//S:Aa|a;
		//A:Sb|b;
		
		_a = new ExtendedTerminalSymbol("a");
		_b = new ExtendedTerminalSymbol("b");
		_S = new ExtendedNonTerminalSymbol("S");
		_A = new ExtendedNonTerminalSymbol("A");
		
		_concat = NonUnaryRegularExpressionOperator.concatenation(_A, _a);
		_pipe = NonUnaryRegularExpressionOperator.pipe(_concat, _a);
		_regex1 = new RegularExpression(_pipe);
		_production1 = new ExtendedProduction(_S, _regex1);
		
		_concat = NonUnaryRegularExpressionOperator.concatenation(_S, _b);
		_pipe = NonUnaryRegularExpressionOperator.pipe(_concat, _b);
		_regex2 = new RegularExpression(_pipe);
		_production2 = new ExtendedProduction(_A, _regex2);


		
		Set<ExtendedProduction> _productions = new HashSet<ExtendedProduction>();
		_productions.add(_production1);
		_productions.add(_production2);
		_productionSet = new ExtendedProductionSet(_productions );
		
		_nonTerminals = new HashSet<ExtendedNonTerminalSymbol>();
		_nonTerminals.add(_S);
		_nonTerminals.add(_A);
		
		_terminals = new HashSet<ExtendedTerminalSymbol>();
		_terminals.add(_a);
		_terminals.add(_b);
		
		_grammar = new ExtendedGrammar(_nonTerminals,_terminals, _productionSet, _S);
		


	}

	
	@After
	public void tearDown() throws Exception {
	}




	@Test
	public void testNullableNT1() {
		
		RegularExpressionElement ree = this.findNonTerminal(_testnull1);	//S
		assertTrue(!_grammar.nullable(ree));
	}
	@Test
	public void testNullableNT2() {
		
		RegularExpressionElement ree = this.findNonTerminal(_testnull2);	//A
		assertFalse(_grammar.nullable(ree));
	}

	
	@Test
	public void testFirsts1() {
		
		RegularExpressionElement ree = this.findNonTerminal(_testfirst1);	//S
		assertTrue(_grammar.firsts(ree).contains(_a));
		assertTrue(_grammar.firsts(ree).contains(_b));
	}
	@Test
	public void testFirsts2() {
		
		RegularExpressionElement ree = this.findNonTerminal(_testfirst2);	//A
		assertTrue(_grammar.firsts(ree).contains(_a));
		assertTrue(_grammar.firsts(ree).contains(_b));
	}


	@Test
	public void testNexts1() {

		assertEquals("[b, $]", _grammar.nexts(this.findNonTerminal(_testnext1)).toString());	//S
	}
	
	@Test
	public void testNexts2() {

		assertEquals("[]", _grammar.nexts(this.findTerminal(_testnext2)).toString());	//a
	}

	@Test
	public void testNexts3() {

		assertEquals("[]", _grammar.nexts(this.findTerminal(_testnext3)).toString());	//b
	}



}
